home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
EnigmA Amiga Run 1996 March
/
EnigmA AMIGA RUN 05 (1996)(G.R. Edizioni)(IT)[!][issue 1996-03][Skylink CD IV].iso
/
earcd
/
dtype
/
txtdt392.lha
/
textdtpatch
/
textdtpatch.c
< prev
next >
Wrap
C/C++ Source or Header
|
1995-11-13
|
17KB
|
717 lines
/*
** $PROJECT: text.datatype patch
**
** $VER: textdtpatch.c 39.2 (11.11.95)
**
** by
**
** Stefan Ruppert , Windthorststraße 5 , 65439 Flörsheim , GERMANY
**
** (C) Copyright 1995
** All Rights Reserved !
**
** $HISTORY:
**
** 11.11.95 : 039.002 : added pattern and case insensetive support
** 04.07.95 : 039.001 : initial
*/
/*FS*//* ----------------------------- version data ----------------------------- */
/* $STARTDEFINE: "BumpRev defines"*/
#define VERSION 39
#define REVISION 2
#define DATE "11.11.95"
#define VERS "textdtpatch 39.2"
#define VSTRING "textdtpatch 39.2 (11.11.95)\r\n"
#define VERSTAG "\0$VER: textdtpatch 39.2 (11.11.95)"
#define NAME "textdtpatch"
/* $ENDDEFINE: */
/*FE*/
/*FS*//* ------------------------------- autodoc -------------------------------- */
/*GB*** textdtpatch **********************************************************
*
* NAME
* textdtpatch - patches the text.datatype to support search method
*
* VERSION
* 39.2
*
* TEMPLATE
* none
*
* REQUIREMENT
* reqtools.library V38, OS3.0 or higher
*
* FUNCTION
* This program patches the text.datatype, so that the new one can
* search for a string. Now it can search by four different ways :
* 1. case sensetive match like strncmp(). Button "Case".
* 2. case insensetive match like Strnicmp(). Button "NoCase".
* 3. case sensetive pattern using MatchPattern(). Button "Pattern".
* 4. case insensetive pattern using MatchPatternNoCase().
* Button "PatternNoCase".
* The following key commands are supported :
*
* Return (STM_ACTIVATE_FIELD) - opens a reqtools requester to enter
* the search string and searches for that if confirmed.
*
* Tab (STM_NEXT_FIELD) , '>' (STM_BROWSE_NEXT) searches for the next
* occurrence of the string.
*
* Shift-Tab (STM_PREV_FIELD) , '<' (STM_BROWSE_PREV) searches for the
* previous occurrence of the string.
*
* INSTALLATION
* 1. Copy textdtpatch to your c: or anywhere you like.
* 2. Add in your S:User-Startup following line:
* run >nil: c:textdtpatch
* 3. To terminate textdtpatch send a break (Ctrl-C).
*
* SEE ALSO
* text.datatype
*
* AUTHOR
* Stefan Ruppert
* Windthorststrasse 5
* 65439 Floersheim Main
* GERMANY
* EMail: ruppert@goofy.zdv.uni-mainz.de
* i511@informatik.fh-wiesbaden.de
* WWW: http://www.uni-mainz.de/~ruppert/
*
*****************************************************************************/
/*FE*/
/*FS*//* ------------------------------- include -------------------------------- */
#include <exec/types.h>
#include <exec/memory.h>
#include <clib/alib_protos.h>
#include <clib/utility_protos.h>
#include <clib/dos_protos.h>
#include <clib/dtclass_protos.h>
#include <clib/exec_protos.h>
#include <clib/intuition_protos.h>
#include <pragmas/utility_pragmas.h>
#include <pragmas/dos_pragmas.h>
#include <pragmas/dtclass_pragmas.h>
#include <pragmas/exec_sysbase_pragmas.h>
#include <pragmas/intuition_pragmas.h>
#include <dos/dostags.h>
#include <datatypes/textclass.h>
#include <clib/reqtools_protos.h>
#include <pragmas/reqtools.h>
#include <libraries/reqtools.h>
#include <string.h>
/*FE*/
/*FS*//* ------------------------- register defintions -------------------------- */
#define RegCall __asm
#define GetA4 __saveds
#define REGA0 register __a0
#define REGA1 register __a1
#define REGA2 register __a2
/*FE*/
/*FS*//* -------------------------- debug definitions --------------------------- */
#ifdef DEBUG
#define bug kprintf
extern void bug(char *fmt,...);
#define D(x) x
#define DB(x) { bug(__FILE__ "(%4ld):" __FUNC__ "() :",__LINE__); \
bug x; \
}
#else
#define bug
#define D(x)
#define DB(x)
#endif
/*FE*/
/*FS*//* -------------------------- static data items --------------------------- */
static const STRPTR version = VERSTAG;
/*FE*/
/*FS*//* ------------------------------ prototypes ------------------------------ */
RegCall GetA4 ULONG mytextdtdispatcher(REGA0 Class *cl,REGA2 Object *obj,REGA1 Msg msg);
ULONG DoAsyncMethod(Class *cl,Object *obj,Msg msg,ULONG tag1,...);
ULONG DoAsyncMethodA(Class *cl,Object *obj,Msg msg,struct TagItem *tagList);
ULONG NotifyAttrs(Object * obj, void * ginfo, ULONG flags, ULONG tag1,...);
ULONG getstring(Class *cl,Object *obj,struct dttGetString *msg);
LONG strseg(struct SegCmp *,struct Line *line);
LONG striseg(struct SegCmp *,struct Line *line);
LONG patseg(struct SegCmp *,struct Line *line);
ULONG searchstring(Class *cl,Object *obj,LONG direction,struct dttSearchText *msg);
/*FE*/
/*FS*//* ------------------------------ definition ------------------------------ */
#define TRG(msg) ((struct dtTrigger *) (msg))
#define SM(msg) ((struct dttGetString *) (msg))
#define DTTM_GETSTRING 0x20000
#define DTTM_SEARCHNEXT 0x20001
#define DTTM_SEARCHPREV 0x20002
struct ClassData
{
struct Library *cd_SysBase;
struct Library *cd_DOSBase;
struct Library *cd_IntuitionBase;
struct Library *cd_UtilityBase;
};
struct dttGetString
{
ULONG MethodID;
struct GadgetInfo dttgs_GInfo;
LONG dttgs_SearchMethod;
};
#define DTTSTM_CASE 1
#define DTTSTM_NOCASE 2
#define DTTSTM_PATTERN 3
#define DTTSTM_PATTERN_NOCASE 4
#define DTTSTM_MAX 5
struct dttSearchText
{
ULONG MethodID;
struct GadgetInfo *dttst_GInfo;
STRPTR dttst_Text;
LONG dttst_TextLen;
LONG dttst_Mode;
};
#define BUFFER_SIZE 128
struct MyTextDTData
{
LONG FoundLine;
LONG LastMode;
struct dttGetString Msg;
UBYTE Buffer[BUFFER_SIZE];
UBYTE PatBuffer[BUFFER_SIZE];
UBYTE TempBuffer[BUFFER_SIZE];
};
struct SegCmp
{
struct ClassData *sc_ClassData;
struct MyTextDTData *sc_InstanceData;
STRPTR sc_String;
LONG sc_StringLen;
STRPTR sc_Buffer;
};
typedef LONG (*CMPSEG)(struct SegCmp *,struct Line *);
#define IntuitionBase cd->cd_IntuitionBase
#define DOSBase cd->cd_DOSBase
#define UtilityBase cd->cd_UtilityBase
/*FE*/
/*FS*//* --------------------------- main entry point --------------------------- */
GetA4 int main(void)
{
struct Library *SysBase = *((struct Library **) 4L);
struct ClassData *cd;
if(SysBase->lib_Version < 39)
return(RETURN_FAIL);
if((cd = AllocVec(sizeof(struct ClassData), MEMF_CLEAR | MEMF_ANY)))
{
struct Library *DTClassBase;
cd->cd_SysBase = SysBase;
DOSBase = OpenLibrary("dos.library",39);
IntuitionBase = OpenLibrary("intuition.library",39);
UtilityBase = OpenLibrary("utility.library",39);
if((DTClassBase = OpenLibrary("datatypes/text.datatype",39)))
{
struct IClass *TextDTClass;
if((TextDTClass = ObtainEngine()))
{
struct IClass *MyTextDTClass;
ClassID oldclassid;
oldclassid = TextDTClass->cl_ID;
TextDTClass->cl_ID = "org_text.datatype";
if((MyTextDTClass = MakeClass("text.datatype",NULL,TextDTClass,sizeof(struct MyTextDTData),0)))
{
MyTextDTClass->cl_Dispatcher.h_Entry = (HOOKFUNC) mytextdtdispatcher;
MyTextDTClass->cl_UserData = (ULONG) cd;
AddClass(MyTextDTClass);
Wait(SIGBREAKF_CTRL_C);
RemoveClass(MyTextDTClass);
while(!FreeClass(MyTextDTClass))
Delay(50);
} else
Printf("can't make new text.datatype class !\n");
TextDTClass->cl_ID = oldclassid;
} else
Printf("can't obtain old text.datatype class !\n");
CloseLibrary(DTClassBase);
} else
Printf("can't open text.datatype !\n");
CloseLibrary(IntuitionBase);
CloseLibrary(DOSBase);
FreeVec(cd);
}
return(RETURN_OK);
}
/*FE*/
/*FS*/ ULONG DoAsyncMethod(Class *cl,Object *obj,Msg msg,ULONG tag1,...)
{
return(DoAsyncMethodA(cl,obj,msg,(struct TagItem *) &tag1));
}
/*FE*/
/*FS*/ /*"ULONG DoAsyncMethodA(Class *cl,Object *obj,Msg msg,struct TagItem *tagList)"*/
struct AsyncMethodMsg
{
struct Message amm_ExecMessage;
Object *amm_Object;
Msg amm_Msg;
};
RegCall GetA4 ULONG asyncmethodfunc(void)
{
struct Library *SysBase = *((struct Library **) 4L);
struct Process *proc = (struct Process *) FindTask(NULL);
Object *obj;
Msg msg;
struct AsyncMethodMsg *amsg;
WaitPort(&proc->pr_MsgPort);
amsg = (struct AsyncMethodMsg *) GetMsg(&proc->pr_MsgPort);
obj = amsg->amm_Object;
msg = amsg->amm_Msg;
ReplyMsg(&amsg->amm_ExecMessage);
D(bug("recieved object : %lx, msg : %lx\n",obj,msg));
return(DoMethodA(obj,msg));
}
#define SysBase cd->cd_SysBase
ULONG DoAsyncMethodA(Class *cl,Object *obj,Msg msg,struct TagItem *tagList)
{
struct ClassData *cd = (struct ClassData *) cl->cl_UserData;
struct AsyncMethodMsg amsg;
struct Process *proc = NULL;
struct MsgPort *mport;
DB(("before CreateMsgPort() !\n"));
if((mport = CreateMsgPort()))
{
DB(("after CreateMsgPort() !\n"));
amsg.amm_Object = obj;
amsg.amm_Msg = msg;
amsg.amm_ExecMessage.mn_Node.ln_Type = NT_MESSAGE;
amsg.amm_ExecMessage.mn_ReplyPort = mport;
DB(("before CreateNewProcTags() !\n"));
if((proc = CreateNewProcTags(NP_Entry,asyncmethodfunc,
(tagList) ? TAG_MORE : TAG_IGNORE,tagList,
TAG_DONE)))
{
DB(("sending object : %lx, msg : %lx\n",obj,msg));
PutMsg(&proc->pr_MsgPort,&amsg.amm_ExecMessage);
WaitPort(mport);
}
DeleteMsgPort(mport);
}
return((ULONG) proc);
}
/*FE*/
/*FS*/ ULONG NotifyAttrs(Object * obj, void * ginfo, ULONG flags, ULONG tag1,...)
{
return(DoMethod(obj, OM_NOTIFY, &tag1, ginfo, flags));
}
/*FE*/
/*FS*/ ULONG getstring(Class *cl,Object *obj,struct dttGetString *msg)
{
struct MyTextDTData *data = INST_DATA(cl,obj);
struct ClassData *cd = (struct ClassData *) cl->cl_UserData;
struct GadgetInfo *ginfo = &msg->dttgs_GInfo;
struct Library *ReqToolsBase;
ULONG retval = 0;
DB(("before getstring() !\n"));
if((ReqToolsBase = OpenLibrary("reqtools.library",38)))
{
retval = rtGetString(data->Buffer,sizeof(data->Buffer),
"Text Datatype Search String",NULL,
RT_Window ,ginfo->gi_Window,
RT_ReqPos ,REQPOS_CENTERWIN,
RT_LockWindow ,TRUE,
RT_Underscore , '_',
RTGS_GadFmt ,"C_ase|_NoCase|_Pattern|PatternN_oCase|_Cancel",
TAG_DONE);
CloseLibrary(ReqToolsBase);
if(retval)
{
data->LastMode = retval;
Forbid();
DoMethod(obj,msg->dttgs_SearchMethod,ginfo,data->Buffer,strlen(data->Buffer),retval);
Permit();
}
}
return(retval);
}
/*FE*/
/*FS*/ LONG strseg(struct SegCmp *cmp,struct Line *line)
{
STRPTR text = line->ln_Text;
STRPTR str = cmp->sc_String;
STRPTR ptr;
LONG slen = cmp->sc_StringLen;
LONG llen = line->ln_TextLen;
LONG len;
while(llen >= slen)
{
ptr = str;
len = slen;
while(*text == *ptr)
{
text++;
ptr++;
llen--;
len--;
}
if(len==0)
return(1);
else
{
text++;
llen--;
}
}
return(0);
}
/*FE*/
/*FS*/ LONG striseg(struct SegCmp *cmp,struct Line *line)
{
struct ClassData *cd = cmp->sc_ClassData;
STRPTR text = line->ln_Text;
STRPTR ptr;
LONG slen = cmp->sc_StringLen;
LONG llen = line->ln_TextLen;
LONG len;
while(llen >= slen)
{
ptr = cmp->sc_String;
len = slen;
while(ToUpper(*text) == *ptr)
{
text++;
ptr++;
llen--;
len--;
}
if(len==0)
return(1);
else
{
text++;
llen--;
}
}
return(0);
}
/*FE*/
/*FS*/ LONG patseg(struct SegCmp *cmp,struct Line *line)
{
struct ClassData *cd = cmp->sc_ClassData;
LONG len = line->ln_TextLen;
if(len > BUFFER_SIZE - 1)
len = BUFFER_SIZE - 1;
strncpy(cmp->sc_Buffer,line->ln_Text,line->ln_TextLen);
cmp->sc_Buffer[len] = 0;
return(MatchPattern(cmp->sc_String,cmp->sc_Buffer));
}
/*FE*/
/*FS*/ LONG patiseg(struct SegCmp *cmp,struct Line *line)
{
struct ClassData *cd = cmp->sc_ClassData;
LONG len = line->ln_TextLen;
if(len > BUFFER_SIZE - 1)
len = BUFFER_SIZE - 1;
strncpy(cmp->sc_Buffer,line->ln_Text,line->ln_TextLen);
cmp->sc_Buffer[len] = 0;
return(MatchPatternNoCase(cmp->sc_String,cmp->sc_Buffer));
}
/*FE*/
/*FS*/ ULONG searchstring(Class *cl,Object *obj,LONG direction,struct dttSearchText *msg)
{
struct ClassData *cd = (struct ClassData *) cl->cl_UserData;
struct MyTextDTData *data = INST_DATA(cl,obj);
struct List *list;
struct SegCmp segcmp;
CMPSEG cmpfuncs[DTTSTM_MAX] = {strseg,striseg,patseg,patiseg};
CMPSEG cmp;
LONG mode = msg->dttst_Mode;
segcmp.sc_ClassData = cd;
segcmp.sc_InstanceData = data;
segcmp.sc_String = msg->dttst_Text;
segcmp.sc_StringLen = msg->dttst_TextLen;
segcmp.sc_Buffer = data->TempBuffer;
switch(msg->dttst_Mode)
{
case DTTSTM_PATTERN_NOCASE:
{
LONG test;
if((test = ParsePatternNoCase(msg->dttst_Text,data->PatBuffer,BUFFER_SIZE)) == 1)
{
segcmp.sc_String = data->PatBuffer;
break;
} else if(test != 0)
{
mode = 0;
break;
} else
mode = DTTSTM_NOCASE;
}
case DTTSTM_NOCASE:
{
STRPTR ptr = data->PatBuffer;
STRPTR text = msg->dttst_Text;
while((*ptr++ = ToUpper(*text++)));
segcmp.sc_String = data->PatBuffer;
}
break;
case DTTSTM_PATTERN:
switch(ParsePattern(msg->dttst_Text,data->PatBuffer,BUFFER_SIZE))
{
case 1:
segcmp.sc_String = data->PatBuffer;
break;
case 0:
mode = DTTSTM_CASE;
break;
default:
mode = 0;
}
break;
}
if(mode > 0 && mode <= DTTSTM_MAX)
{
cmp = cmpfuncs[mode-1];
DB(("search for : \"%s\" !\n",msg->dttst_Text));
if(GetAttr(TDTA_LineList,obj,(ULONG *) &list))
{
struct Line *line;
LONG len = msg->dttst_TextLen;
LONG found = data->FoundLine;
LONG y = 0;
strcpy(data->TempBuffer,msg->dttst_Text);
line = (struct Line *) list->lh_Head;
if(direction == -1)
found--;
while(y <= found && line->ln_Link.mln_Succ)
{
if(line->ln_Flags & LNF_LF)
y++;
line = (struct Line *) line->ln_Link.mln_Succ;
}
found = -1;
if(direction == -1)
{
if(line->ln_Link.mln_Pred)
line = (struct Line *) line->ln_Link.mln_Pred;
while(line->ln_Link.mln_Pred && found == -1)
{
if(line->ln_Flags & LNF_LF)
y--;
if(line->ln_TextLen >= len)
{
if(cmp(&segcmp,line))
{
found = y;
break;
}
}
line = (struct Line *) line->ln_Link.mln_Pred;
}
} else
{
while(line->ln_Link.mln_Succ && found == -1)
{
if(line->ln_TextLen >= len)
{
if(cmp(&segcmp,line))
{
found = y;
break;
}
}
if(line->ln_Flags & LNF_LF)
y++;
line = (struct Line *) line->ln_Link.mln_Succ;
}
}
if(found < 0)
{
DisplayBeep(msg->dttst_GInfo->gi_Screen);
if(data->FoundLine >= 0)
NotifyAttrs(obj,msg->dttst_GInfo,0,DTA_TopVert,data->FoundLine,TAG_DONE);
} else
{
data->FoundLine = found;
NotifyAttrs(obj,msg->dttst_GInfo,0,DTA_TopVert,found,TAG_DONE);
}
}
}
return(0);
}
/*FE*/
/*FS*/ RegCall GetA4 ULONG mytextdtdispatcher(REGA0 Class *cl,REGA2 Object *obj,REGA1 Msg msg)
{
struct MyTextDTData *data = INST_DATA(cl,obj);
ULONG retval = 0;
switch(msg->MethodID)
{
case OM_NEW:
{
Object *newobj;
if((newobj = (Object *) DoSuperMethodA(cl,obj,msg)))
{
data = INST_DATA(cl,newobj);
data->FoundLine = -1;
data->LastMode = 1;
DB(("new text.datatype object : %lx\n",newobj));
retval = (ULONG) newobj;
}
}
break;
case DTM_TRIGGER:
{
ULONG searchmethod = DTTM_SEARCHNEXT;
switch(TRG(msg)->dtt_Function)
{
case STM_PREV_FIELD:
case STM_BROWSE_PREV:
searchmethod = DTTM_SEARCHPREV;
case STM_NEXT_FIELD:
case STM_BROWSE_NEXT:
if(data->Buffer[0])
{
DoMethod(obj,searchmethod,TRG(msg)->dtt_GInfo,data->Buffer,strlen(data->Buffer),data->LastMode);
break;
}
case STM_ACTIVATE_FIELD:
data->Msg.MethodID = DTTM_GETSTRING;
/* copy the full GadgetInfo, because this request is asyncron and datatypes
* creates this structure on the stack (Oh No) !
*/
data->Msg.dttgs_GInfo = *TRG(msg)->dtt_GInfo;
data->Msg.dttgs_SearchMethod = searchmethod;
DB(("before async method !\n"));
DoAsyncMethod(cl,obj,(Msg) &data->Msg,NP_Name,"text.datatype getstring process",TAG_DONE);
break;
}
}
break;
case DTTM_GETSTRING:
retval = getstring(cl,obj,(struct dttGetString *) msg);
break;
case DTTM_SEARCHNEXT:
retval = searchstring(cl,obj,1,(struct dttSearchText *) msg);
break;
case DTTM_SEARCHPREV:
retval = searchstring(cl,obj,-1,(struct dttSearchText *) msg);
break;
default:
retval = DoSuperMethodA(cl,obj,msg);
}
return(retval);
}
/*FE*/